package com.example.skinmanager.Factory;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatDelegate;

import com.example.skinmanager.Bean.SkinItem;
import com.example.skinmanager.Bean.SkinView;
import com.example.skinmanager.R;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class SkinFactory implements LayoutInflater.Factory2 {
    private static  HashMap<String, Constructor<? extends View>> sConstructorMap =
            new HashMap<String, Constructor<? extends View>>();
    private static  Class<?>[] mConstructorSignature = new Class[] {
            Context.class, AttributeSet.class};
    private static final String[] prxfixList = {
            "android.widget.",
            "android.view.",
            "android.webkit."
    };
    private List<SkinView> skinViews = new ArrayList<>();
    private AppCompatDelegate delegate;
        //通过delegate中的方法来实例化对象
    public SkinFactory(AppCompatDelegate delegate) {
        this.delegate = delegate;
    }



    @Nullable
    @Override
    public View onCreateView(@Nullable View parent, @NonNull String name, @NonNull Context context, @NonNull AttributeSet attrs) {
        View currentView = null;
        if (delegate != null){
            //继承自AppCompatActivity情况
            currentView = delegate.createView(parent, name, context, attrs);
        }else {
            //继承自Activity情况
            if (name.contains(".")){
                currentView = onCreateView(name, context, attrs);
            }else {
                for(String s : prxfixList){
                    String clazzName = s+name;
                    currentView = onCreateView(clazzName, context, attrs);
                    if (currentView !=null){
                        return currentView;
                    }
                }

            }
        }
        //此处完成view的实例化之后 进行自定义操作 收集需要换肤的控件
        if (currentView != null){
            parseView(context,currentView,attrs);
        }


        return currentView;
    }


    @Nullable
    @Override
    public View onCreateView(@NonNull String name, @NonNull Context context, @NonNull AttributeSet attrs) {
        View view = null;
        try {
            Class aClass = context.getClassLoader().loadClass(name);
            Constructor<? extends View> constructor = sConstructorMap.get(name);
            if (constructor == null) {
                constructor = aClass.getConstructor(mConstructorSignature);
                sConstructorMap.put(name,constructor);

            }
            view = constructor.newInstance(context,attrs);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return view;
    }

    private void parseView(Context context, View currentView, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.skinAble);
        boolean isSkin = typedArray.getBoolean(R.styleable.skinAble_is_skin, false);
        if (!isSkin){
            return;
        }
        List<SkinItem> list = new ArrayList<>();
        for (int i = 0; i < attrs.getAttributeCount(); i++){
            String attributeName = attrs.getAttributeName(i);
            if (attributeName.contains("background")||attributeName.contains("textColor")||
                    attributeName.contains("src")){
                String resIdStr = attrs.getAttributeValue(i);
                int resId = Integer.parseInt(resIdStr.substring(1));
                String resourceTypeName = context.getResources().getResourceTypeName(resId);
                String resourceEntryName = context.getResources().getResourceEntryName(resId);
                SkinItem skinItem = new SkinItem(attributeName,resourceTypeName,resourceEntryName,resId);
                list.add(skinItem);
            }
        }
        if (list.size()>0){
            SkinView skinView = new SkinView(list,currentView);
            skinViews.add(skinView);
        }
    }
    public void apply(){
        for (SkinView skinView :skinViews){
            skinView.apply();
        }
    }
}
